﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Web;
using System.Text;
using Ue.Framework;
using Ue.Framework.Web;
using Ue.Framework.Collections;
using Ue.Infrastructure;
using Ue.Infrastructure.RepositoryFramework;
using Ue.Qcdz.Domain;
using Ue.Qcdz.Domain.TreeViews;
using Ue.Qcdz.Domain.Tags;
using Ue.Qcdz.Domain.ContentTypes;

namespace Ue.Qcdz.UI.Controller
{
    public class TreeViewController : Ue.Infrastructure.Web.AsyncHandlers.AsyncResult
    {
        private TreeView treeView;
        private object isLoaded = new object();
        private ITreeViewRepository treeViewRepository;
        private ITagRepository tagRepository;
        private IUnitOfWork uniteOfWork;
     

        public TreeViewController(AsyncCallback callback, HttpContext context, object state)
            : base(callback, context, state)
        {
            this.uniteOfWork = new UnitOfWork();
            this.treeViewRepository = RepositoryFactory.GetRepository<ITreeViewRepository, TreeView>(this.uniteOfWork);
            this.tagRepository = RepositoryFactory.GetRepository<ITagRepository, Tag>(this.uniteOfWork);
            this.treeView = this.treeViewRepository[context.Request.GetQueryValue<Guid>("TreeViewId")];
        }

        public void DeleteNode()
        {
            this.treeView.Remove(this.CurrentNode);

            this.tagRepository.Remove((Tag)this.CurrentNode.Tag);
            this.treeViewRepository[this.treeView.Key] = this.treeView;
            this.uniteOfWork.Commit();
        }

        public string UpdateNode()
        {
            this.treeView.Update(this.CurrentNode);

            this.tagRepository[this.CurrentNode.Tag.Key] = (Tag)this.CurrentNode.Tag;
            this.treeViewRepository[this.treeView.Key] = this.treeView;
            this.uniteOfWork.Commit();

            return RenderCurrentNodeHtml();
        }

        public string RenderCurrentNodeHtml()
        {
            StringBuilder builder = new StringBuilder();
            this.BuildTreeNode(builder, this.CurrentNode);
            return builder.ToString();
        }

        public string RenderTreeViewHtml()
        {
            StringBuilder htmlBuilder = new StringBuilder();
            IList<TreeNode> nodes = this.treeView.ChildNodes.ToList();
            htmlBuilder.Append("<ul>");
            nodes.Foreach(node => { this.BuildTreeNode(htmlBuilder, node); });
            htmlBuilder.Append("</ul>");

            return htmlBuilder.ToString();
        }
        private void BuildTreeNode(StringBuilder builder, TreeNode node)
        {
            IList<TreeNode> childNodes = node.ChildNodes.ToList();

            bool hasChildNode = childNodes.Count > 0;

            builder.Append("<li>");
            builder.Append(string.Format(
                "<span class=\"{0}\"><a href=\"javascript:void(0);\" id=\"{1}\" parentId=\"{2}\" tagId=\"{3}\" title=\"{4}\">{5}</a></span>",
                hasChildNode ? "folder" : "file",
                node.Key,
                (node.Parent == null || node.Parent.Key == null) ? string.Empty : node.Parent.Key.ToString(),
                node.Tag.Key,
                ((Tag)node.Tag).Description,
                node.Tag.Name));

            if (hasChildNode)
            {
                builder.Append("<ul>");
                childNodes.Foreach(childNode => this.BuildTreeNode(builder, childNode));
                builder.Append("</ul>");
            }

            builder.Append("</li>");
        }

        public ContentType GetContentType()
        {
            Guid? contentTypeKey = this.Context.Request.GetQueryValue<Guid?>("ContentTypeId");

            return contentTypeKey != null
                ? ContentTypeService.Instance.FindBy(contentTypeKey.Value)
                : TreeViewService.Instance.ContentType;
        }

        private Tag currentTag;
        public Tag CurrentTag
        {
            get
            {
                if (currentTag == null)
                {
                    Guid? tagId = this.Context.Request.GetQueryValue<Guid?>("TagId");
                    currentTag = this.tagRepository[tagId];
                    if (currentTag == null)
                    {
                        currentTag = new Tag(this.GetContentType());
                    }

                    currentTag.Name = this.Context.Request.GetQueryValue<string>("TagName");
                    currentTag.Description = this.Context.Request.GetQueryValue<string>("TagDescription");
                }

                return this.currentTag;
            }
        }

        private TreeNode currentNode;
        public TreeNode CurrentNode
        {
            get
            {
                if (currentNode == null)
                {
                    this.currentNode = this.treeView.FindNodeBy(
                        this.Context.Request.GetQueryValue<Guid?>("NodeId"));

                    if (this.currentNode == null)
                    {
                        TreeNode parentNode = this.treeView.FindNodeBy(
                            this.Context.Request.GetQueryValue<Guid?>("ParentId"));

                        this.currentNode = this.treeView.CreateNode(parentNode, this.CurrentTag);
                    }
                    else
                    {
                        this.currentNode.Tag.Name = this.CurrentTag.Name;
                        ((Tag)this.currentNode.Tag).Description = this.CurrentTag.Description;
                    }
                }

                return this.currentNode;
            }
        }
    }
}
